// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004-2009 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using SoapTrace.Core.Formatters;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace SoapTrace.Core.Gui
{
	public partial class SoapMessageFormatterConfigForm : Form
	{
		/// <summary>
		/// The editor associated with this form.
		/// </summary>
		private FormatterConfigurationEditor m_Editor;

		/// <summary>
		/// The currently selected web service operation.
		/// </summary>
		private WebServiceOperation m_SelectedWebServiceOperation;

		/// <summary>
		/// Flag to indicate whether events should be raised.
		/// </summary>
		private bool FireEvents = true;

		/// <summary>
		/// Creates a new instance of the <see cref="SoapMessageFormatterConfigForm"/>.
		/// </summary>
		/// <param name="editor">The controller for this form.</param>
		public SoapMessageFormatterConfigForm( FormatterConfigurationEditor editor )
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent( );

			m_Editor = editor;
		}
		
		/// <summary>
		/// Displays an error message to the user.
		/// </summary>
		/// <param name="message">The message to display.</param>
		public static void ShowError( string message )
		{
			MessageBox.Show( message, "", MessageBoxButtons.OK, MessageBoxIcon.Error );
		}

		/// <summary>
		/// Adds the web services to the form.
		/// </summary>
		/// <param name="webServices">A collection of web services.</param>
		public void AddWebServices( WebServiceCollection webServices )
		{
			foreach( WebService WebService in webServices )
			{
				AddWebService( WebService );
			}
		}

		/// <summary>
		/// Adds a single web service to the config form.
		/// </summary>
		/// <param name="webService">A web service.</param>
		public void AddWebService( WebService webService )
		{
			TreeNode WebServiceNode = AddWebServiceNode( webService );

			foreach( WebServiceOperation Operation in webService.Operations )
			{
				AddWebServiceOperationNode( WebServiceNode, Operation );
			}
		}

		/// <summary>
		/// Gets or sets the web service operation name.
		/// </summary>
		public string WebServiceOperationName
		{
			[ DebuggerStepThrough ]
			get
			{
				return WebServiceOperationNameTextBox.Text;
			}

			[ DebuggerStepThrough ]
			set
			{
				WebServiceOperationNameTextBox.Text = value;
			}
		}

		/// <summary>
		/// Adds the parameters to right hand side display.
		/// </summary>
		/// <param name="parameters">The parameters to display.</param>
		public void AddParameters( WebServiceParameterCollection parameters )
		{
			foreach( WebServiceParameter Parameter in parameters )
			{
				AddParameter( Parameter );
			}
		}

		/// <summary>
		/// Adds a parameter to the right hand side of the display.
		/// </summary>
		/// <param name="parameter">The parameter to add.</param>
		public void AddParameter( WebServiceParameter parameter )
		{
			ParametersListBox.Items.Add( parameter.Name );
		}

		/// <summary>
		/// Adds a return value to the right hand side of the display.
		/// </summary>
		/// <param name="returnValue">The return value to add.</param>
		public void AddReturnValue( WebServiceReturnValue returnValue )
		{
			try
			{
				FireEvents = false;
				ReturnValuesListBox.Items.Add( returnValue.Name );
			}
			finally
			{
				FireEvents = true;
			}
		}

		/// <summary>
		/// Clears the displayed web service's parameters and return values.
		/// </summary>
		public void ClearSelectedWebServiceOperation( )
		{
			try
			{
				FireEvents = false;

				ParametersListBox.Items.Clear( );
				ParameterTypeComboBox.Text = String.Empty;
				DisplayParameterCheckBox.Checked = false;
				ParameterNameTextBox.Text = String.Empty;

				ReturnValuesListBox.Items.Clear( );
				ReturnValueTypeComboBox.Text = String.Empty;
				DisplayReturnValueCheckBox.Checked = false;
				ReturnValueNameTextBox.Text = String.Empty;
			}
			finally
			{
				FireEvents = true;
			}
		}

		/// <summary>
		/// Gets or sets the currently selected parameter's name.
		/// </summary>
		public string ParameterName
		{
			[ DebuggerStepThrough ]
			get
			{
				return ParameterNameTextBox.Text;
			}

			[ DebuggerStepThrough ]
			set
			{
				ParameterNameTextBox.Text = value;
			}
		}

		/// <summary>
		/// Gets or sets the currently selected parameter's type.
		/// </summary>
		public string ParameterType
		{
			[ DebuggerStepThrough ]
			get
			{
				return ParameterTypeComboBox.Text;
			}

			[ DebuggerStepThrough ]
			set
			{
				FireEvents = false;
				ParameterTypeComboBox.Text = value;
				FireEvents = true;
			}
		}

		/// <summary>
		/// Gets or sets the currently selected parameter's display property.
		/// </summary>
		public bool DisplayParameter
		{
			[ DebuggerStepThrough ]
			get
			{
				return DisplayParameterCheckBox.Checked;
			}

			[ DebuggerStepThrough ]
			set
			{
				FireEvents = false;
				DisplayParameterCheckBox.Checked = value;
				FireEvents = true;
			}
		}

		/// <summary>
		/// Gets or sets the currently selected return value's name.
		/// </summary>
		public string ReturnValueName
		{
			[ DebuggerStepThrough ]
			get
			{
				return ReturnValueNameTextBox.Text;
			}

			[ DebuggerStepThrough ]
			set
			{
				ReturnValueNameTextBox.Text = value;
			}
		}

		/// <summary>
		/// Clears the form of all entries.
		/// </summary>
		public void Clear( )
		{
			ClearSelectedWebServiceOperation( );
			WebServicesTreeView.Nodes.Clear( );
		}

		/// <summary>
		/// Gets or sets the currently selected return value's type.
		/// </summary>
		public string ReturnValueType
		{
			[ DebuggerStepThrough ]
			get
			{
				return ReturnValueTypeComboBox.Text;
			}

			[ DebuggerStepThrough ]
			set
			{
				FireEvents = false;
				ReturnValueTypeComboBox.Text = value;
				FireEvents = true;
			}
		}

		/// <summary>
		/// Gets or sets the currently selected return value's display property.
		/// </summary>
		public bool DisplayReturnValue
		{
			[ DebuggerStepThrough ]
			get
			{
				return DisplayReturnValueCheckBox.Checked;
			}

			[ DebuggerStepThrough ]
			set
			{
				FireEvents = false;
				DisplayReturnValueCheckBox.Checked = value;
				FireEvents = true;
			}
		}

		/// <summary>
		/// Adds supported parameter types to the parameter type drop down.
		/// </summary>
		/// <param name="types">A string array of parameter types.</param>
		public void AddParameterTypes( string[ ] types )
		{
			foreach( string parameterType in types )
			{
				AddParameterType( parameterType );
			}
		}

		/// <summary>
		/// Adds a supported parameter type to the parameter type drop down.
		/// </summary>
		/// <param name="parameterType">The parameter type.</param>
		public void AddParameterType( string parameterType )
		{
			ParameterTypeComboBox.Items.Add( parameterType );
		}

		/// <summary>
		/// Adds supported return value types to the return value type drop down.
		/// </summary>
		/// <param name="types">A string array of return value types.</param>
		public void AddReturnValueTypes( string[ ] types )
		{
			foreach( string ReturnValueType in types )
			{
				AddReturnValueType( ReturnValueType );
			}
		}

		/// <summary>
		/// Adds a supported return value type to the return value type drop down.
		/// </summary>
		/// <param name="returnValueType">The return value type.</param>
		public void AddReturnValueType( string returnValueType )
		{
			ReturnValueTypeComboBox.Items.Add( returnValueType );
		}

		/// <summary>
		/// Returns the currently selected web service operation.
		/// </summary>
		public WebServiceOperation SelectedWebServiceOperation
		{
			[ DebuggerStepThrough ]
			get
			{
				return m_SelectedWebServiceOperation;
			}
		}

		/// <summary>
		/// Returns the currently selected return value.
		/// </summary>
		public WebServiceReturnValue SelectedReturnValue
		{
			get
			{
				WebServiceReturnValue ReturnValue = null;

				WebServiceOperation Operation = SelectedWebServiceOperation;

				if( Operation != null )
				{
					int SelectedIndex = ReturnValuesListBox.SelectedIndex;

					if( SelectedIndex != -1 )
					{
						ReturnValue = Operation.ReturnValue;
					}
				}

				return ReturnValue;
			}
		}

		/// <summary>
		/// Returns the currently selected parameter.
		/// </summary>
		public WebServiceParameter SelectedParameter
		{
			get
			{
				WebServiceParameter Parameter = null;

				WebServiceOperation Operation = SelectedWebServiceOperation;

				if( Operation != null )
				{
					int SelectedIndex = ParametersListBox.SelectedIndex;

					if( SelectedIndex != -1 )
					{
						Parameter = Operation.Parameters[ SelectedIndex ];
					}
				}

				return Parameter;
			}
		}

		/// <summary>
		/// Adds a web service node to the tree.
		/// </summary>
		/// <param name="webService">The web service object to add.</param>
		/// <returns>The web service node that has been added. </returns>
		private TreeNode AddWebServiceNode( WebService webService )
		{
			TreeNode NewNode = new TreeNode( webService.Name );
			NewNode.Tag = webService;

			WebServicesTreeView.Nodes.Add( NewNode );

			return NewNode;
		}

		/// <summary>
		/// Adds a web service operation to its parent web service node.
		/// </summary>
		/// <param name="parentNode">The web service parent node.</param>
		/// <param name="operation">The web service operation.</param>
		/// <returns>Returns the newly added tree node.</returns>
		private static TreeNode AddWebServiceOperationNode( TreeNode parentNode,
			WebServiceOperation operation )
		{
			TreeNode NewNode = new TreeNode( operation.Name );
			NewNode.Tag = operation;
			
			parentNode.Nodes.Add( NewNode );

			return NewNode;
		}

		/// <summary>
		/// Handles the tree view after select event.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void WebServicesTreeViewAfterSelect( object sender, TreeViewEventArgs e )
		{
			m_SelectedWebServiceOperation = GetSelectedWebServiceOperation( e.Node );
			m_Editor.WebServiceOperationSelected( m_SelectedWebServiceOperation );
		}

		/// <summary>
		/// Handles the parameter selection changed event.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void ParametersListBoxSelectedIndexChanged( object sender, EventArgs e )
		{
			if( FireEvents )
			{
				m_Editor.ParameterSelected( SelectedParameter );
			}
		}

		/// <summary>
		/// The user clicked the OK button.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void FormOKButtonClick( object sender, EventArgs e )
		{
			m_Editor.SaveChanges( );
			Close( );
		}

		/// <summary>
		/// Handles the return value list box selected index changed event.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void ReturnValuesListBoxSelectedIndexChanged( object sender, EventArgs e )
		{
			if( FireEvents )
			{
				m_Editor.ReturnValueSelected( SelectedReturnValue );
			}
		}

		/// <summary>
		/// User clicked the cancel button.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void FormCancelButtonClick( object sender, EventArgs e )
		{
			m_Editor.UndoChanges( );
			Close( );
		}

		/// <summary>
		/// The user has changed the parameter type's text.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void ParameterTypeComboBoxTextChanged( object sender, 
			EventArgs e )
		{
			if( FireEvents )
			{
				m_Editor.ParameterTypeChanged( SelectedParameter );
			}
		}

		/// <summary>
		/// Gets the selected web service operation from the node.
		/// </summary>
		/// <param name="selectedNode">The selected tree node.</param>
		/// <returns>The web service operation selected or null.</returns>
		private static WebServiceOperation GetSelectedWebServiceOperation( TreeNode selectedNode )
		{
			WebServiceOperation Operation = null;

			if( selectedNode != null )
			{
				Operation = selectedNode.Tag as WebServiceOperation;
			}

			return Operation;
		}

		/// <summary>
		/// User has changed the return value type.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void ReturnValueTypeComboBoxTextChanged( object sender, 
			System.EventArgs e )
		{
			if( FireEvents )
			{
				m_Editor.ReturnValueTypeChanged( SelectedReturnValue );
			}
		}

		/// <summary>
		/// User changed the check box state of the ReturnValue.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void DisplayReturnValueCheckBoxCheckedChanged( object sender,
			EventArgs e )
		{
			if( FireEvents )
			{
				m_Editor.DisplayReturnValueChanged( SelectedReturnValue );
			}
		}

		/// <summary>
		/// User changed the check box state of the parameter.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void DisplayParameterCheckBoxCheckedChanged( object sender, 
			EventArgs e )
		{
			if( FireEvents )
			{
				m_Editor.DisplayParameterChanged( SelectedParameter );
			}
		}
		
		/// <summary>
		/// User clicked the <see cref="AddWebServiceButton"/>.
		/// </summary>
		/// <param name="sender">The object that triggered this event.</param>
		/// <param name="e">The event arguments.</param>
		private void AddWebServiceButtonClick( object sender, EventArgs e )
		{
			m_Editor.AddWebService( UrlTextBox.Text );
		}
		
		/// <summary>
		/// Sets the initial start position if the form has an
		/// owner.
		/// </summary>
		/// <remarks>
		/// If the form is not recreated each time then a call
		/// to ShowDialog does not centre the dialog to its parent
		/// so here we force it to be centred.
		/// </remarks>
		private void SetFormStartPosition( )
		{
			if( Owner != null )
			{
				int x = Owner.Location.X + ( Owner.Width / 2 ) - ( Width / 2 );
            	int y = Owner.Location.Y + ( Owner.Height / 2 ) - ( Height / 2 );
            	Location = new Point( x, y );
			}
		}
		
		/// <summary>
		/// On form load we set the form's position if it has an owner.
		/// </summary>
		/// <param name="sender">The event source.</param>
		/// <param name="e">The event arguments.</param>
		void SoapMessageFormatterConfigFormLoad( object sender, EventArgs e )
		{
			SetFormStartPosition( );
		}
		
	}
}
